//! 配置广播集成功能
//! 
//! 通过消息总线实现配置变更事件的自动广播和集群同步

use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::SystemTime;
use crate::error::ConfigResult;

/// 配置广播事件类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ConfigBroadcastEventType {
    /// 配置更新事件
    ConfigUpdate,
    /// 配置删除事件
    ConfigDelete,
    /// 配置刷新事件  
    ConfigRefresh,
    /// 服务重启请求事件
    ServiceRestart,
}

/// 配置广播事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfigBroadcastEvent {
    /// 事件ID
    pub id: String,
    /// 事件类型
    pub event_type: ConfigBroadcastEventType,
    /// 应用名称
    pub application: String,
    /// 配置文件（profile）
    pub profile: String,
    /// 标签（branch/label）
    pub label: Option<String>,
    /// 配置键路径
    pub config_path: Option<String>,
    /// 变更前的值
    pub old_value: Option<serde_json::Value>,
    /// 变更后的值
    pub new_value: Option<serde_json::Value>,
    /// 触发源服务
    pub source_service: String,
    /// 目标服务（可选，为空表示广播给所有服务）
    pub target_services: Option<Vec<String>>,
    /// 事件时间戳
    pub timestamp: SystemTime,
    /// 操作用户
    pub user: Option<String>,
    /// 附加元数据
    pub metadata: HashMap<String, String>,
}

/// 配置广播器 trait - 负责发送配置变更事件
#[async_trait]
pub trait ConfigBroadcaster: Send + Sync {
    /// 广播配置更新事件
    async fn broadcast_config_update(
        &self,
        application: &str,
        profile: &str,
        label: Option<&str>,
        config_path: &str,
        old_value: Option<serde_json::Value>,
        new_value: serde_json::Value,
        user: Option<&str>,
    ) -> ConfigResult<()>;
    
    /// 广播配置删除事件
    async fn broadcast_config_delete(
        &self,
        application: &str,
        profile: &str,
        label: Option<&str>,
        config_path: &str,
        user: Option<&str>,
    ) -> ConfigResult<()>;
    
    /// 广播配置刷新请求
    async fn broadcast_config_refresh(
        &self,
        application: &str,
        profile: &str,
        target_services: Option<Vec<String>>,
    ) -> ConfigResult<()>;
    
    /// 广播服务重启请求
    async fn broadcast_service_restart(
        &self,
        application: &str,
        target_services: Option<Vec<String>>,
        user: Option<&str>,
    ) -> ConfigResult<()>;
}

/// 配置广播监听器 trait - 负责处理收到的配置变更事件
#[async_trait]
pub trait ConfigBroadcastListener: Send + Sync {
    /// 处理配置变更事件
    async fn on_config_change(&self, event: &ConfigBroadcastEvent) -> ConfigResult<()>;
    
    /// 获取监听器名称
    fn name(&self) -> &str;
    
    /// 是否关心此事件（过滤器）
    fn should_handle(&self, event: &ConfigBroadcastEvent) -> bool {
        true
    }
    
    /// 获取关注的应用列表（为空表示关注所有应用）
    fn interested_applications(&self) -> Vec<String> {
        vec![]
    }
}

/// 配置广播管理器 trait - 统一管理广播和监听
#[async_trait]
pub trait ConfigBroadcastManager: ConfigBroadcaster + Send + Sync {
    /// 启动广播管理器
    async fn start(&self) -> ConfigResult<()>;
    
    /// 停止广播管理器
    async fn stop(&self) -> ConfigResult<()>;
    
    /// 注册配置变更监听器
    async fn register_listener(&self, listener: Box<dyn ConfigBroadcastListener>);
    
    /// 移除配置变更监听器
    async fn remove_listener(&self, name: &str) -> bool;
    
    /// 获取集群状态
    async fn get_cluster_state(&self) -> HashMap<String, ServiceState>;
    
    /// 获取广播统计信息
    async fn get_broadcast_stats(&self) -> BroadcastStats;
}

/// 服务状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceState {
    /// 服务名称
    pub service_name: String,
    /// 最后心跳时间
    pub last_heartbeat: SystemTime,
    /// 配置版本
    pub config_version: String,
    /// 服务状态
    pub status: ServiceStatus,
    /// 附加信息
    pub metadata: HashMap<String, String>,
}

/// 服务状态枚举
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ServiceStatus {
    /// 运行中
    Running,
    /// 重启中
    Restarting,
    /// 停止
    Stopped,
    /// 配置同步中
    Syncing,
}

/// 广播统计信息
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct BroadcastStats {
    /// 发送的事件数量
    pub events_sent: u64,
    /// 接收的事件数量
    pub events_received: u64,
    /// 处理成功的事件数量
    pub events_processed: u64,
    /// 处理失败的事件数量
    pub events_failed: u64,
    /// 最后处理时间
    pub last_processed: Option<SystemTime>,
    /// 活跃的监听器数量
    pub active_listeners: u32,
}

impl ConfigBroadcastEventType {
    /// 转换为字符串
    pub fn as_str(&self) -> &'static str {
        match self {
            ConfigBroadcastEventType::ConfigUpdate => "config.update",
            ConfigBroadcastEventType::ConfigDelete => "config.delete", 
            ConfigBroadcastEventType::ConfigRefresh => "config.refresh",
            ConfigBroadcastEventType::ServiceRestart => "service.restart",
        }
    }
}

impl ConfigBroadcastEvent {
    /// 创建配置更新事件
    pub fn config_update(
        application: &str,
        profile: &str,
        label: Option<&str>,
        config_path: &str,
        old_value: Option<serde_json::Value>,
        new_value: serde_json::Value,
        source_service: &str,
        user: Option<&str>,
    ) -> Self {
        Self {
            id: format!("config_update_{}", SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_nanos()),
            event_type: ConfigBroadcastEventType::ConfigUpdate,
            application: application.to_string(),
            profile: profile.to_string(),
            label: label.map(|s| s.to_string()),
            config_path: Some(config_path.to_string()),
            old_value,
            new_value: Some(new_value),
            source_service: source_service.to_string(),
            target_services: None,
            timestamp: SystemTime::now(),
            user: user.map(|s| s.to_string()),
            metadata: HashMap::new(),
        }
    }
    
    /// 创建服务重启请求事件
    pub fn service_restart(
        application: &str,
        source_service: &str,
        target_services: Option<Vec<String>>,
        user: Option<&str>,
    ) -> Self {
        Self {
            id: format!("service_restart_{}", SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_nanos()),
            event_type: ConfigBroadcastEventType::ServiceRestart,
            application: application.to_string(),
            profile: String::new(),
            label: None,
            config_path: None,
            old_value: None,
            new_value: None,
            source_service: source_service.to_string(),
            target_services,
            timestamp: SystemTime::now(),
            user: user.map(|s| s.to_string()),
            metadata: HashMap::new(),
        }
    }
    
    /// 创建配置刷新事件
    pub fn config_refresh(
        application: &str,
        profile: &str,
        source_service: &str,
        target_services: Option<Vec<String>>,
    ) -> Self {
        Self {
            id: format!("config_refresh_{}", SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_nanos()),
            event_type: ConfigBroadcastEventType::ConfigRefresh,
            application: application.to_string(),
            profile: profile.to_string(),
            label: None,
            config_path: None,
            old_value: None,
            new_value: None,
            source_service: source_service.to_string(),
            target_services,
            timestamp: SystemTime::now(),
            user: None,
            metadata: HashMap::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_config_broadcast_event_creation() {
        let event = ConfigBroadcastEvent::config_update(
            "user-service",
            "prod", 
            Some("v1.0"),
            "database.url",
            Some(serde_json::Value::String("old-url".to_string())),
            serde_json::Value::String("new-url".to_string()),
            "config-server",
            Some("admin"),
        );
        
        assert_eq!(event.application, "user-service");
        assert_eq!(event.profile, "prod");
        assert_eq!(event.label, Some("v1.0".to_string()));
        assert_eq!(event.event_type, ConfigBroadcastEventType::ConfigUpdate);
        assert_eq!(event.source_service, "config-server");
        assert_eq!(event.user, Some("admin".to_string()));
    }
    
    #[test]
    fn test_event_type_as_str() {
        assert_eq!(ConfigBroadcastEventType::ConfigUpdate.as_str(), "config.update");
        assert_eq!(ConfigBroadcastEventType::ConfigDelete.as_str(), "config.delete");
        assert_eq!(ConfigBroadcastEventType::ConfigRefresh.as_str(), "config.refresh");
        assert_eq!(ConfigBroadcastEventType::ServiceRestart.as_str(), "service.restart");
    }
}